Skip to content

Theme switcher groundwork: ThemeVariant field through API + state#7756

Open
renemadsen wants to merge 9 commits intostablefrom
feature/theme-switcher-workspace
Open

Theme switcher groundwork: ThemeVariant field through API + state#7756
renemadsen wants to merge 9 commits intostablefrom
feature/theme-switcher-workspace

Conversation

@renemadsen
Copy link
Copy Markdown
Member

Summary

  • Adds ThemeVariant to user settings: wired from EformUser (BasePn 10.0.18) through host API models (UserSettingsModel, UserInfoViewModel), services (AccountService, AdminService), and Angular auth state (model, action, reducer, selector)
  • Bumps Microting.eFormApi.BasePn 10.0.17 → 10.0.18 and Microting.EformAngularFrontendBase 10.0.21 → 10.0.22 to pick up the new property and DB migration
  • Groundwork only — SCSS token work, layout body-class switching, and the profile-settings theme picker come in follow-up commits on this branch

Background

Part of a larger effort to let users choose between the current eForm look and a Google-Workspace-style theme. The preference is orthogonal to the existing dark-mode toggle (theme × appearance are independent). Design notes in ~/.claude/plans/lexical-frolicking-hollerith.md.

Test plan

  • Backend builds (dotnet build eFormAPI/eFormAPI.sln) — verified locally, 0 errors
  • Frontend builds (cd eform-client && npm run build)
  • GET /api/account/user-settings returns themeVariant: "eform" for existing users
  • PUT /api/account/user-settings with themeVariant: "workspace" persists to DB
  • Existing dark-mode toggle still works unchanged
  • User list (GET /api/users) includes themeVariant per user

🤖 Generated with Claude Code

renemadsen and others added 9 commits April 11, 2026 11:10
Threads the new EformUser.ThemeVariant field through host API models
(UserSettingsModel, UserInfoViewModel) and services (AccountService,
AdminService), and adds matching fields/actions/selectors to the
Angular auth state. No UI yet — SCSS tokens and picker come next.

Also bumps Microting.eFormApi.BasePn to 10.0.18 and
Microting.EformAngularFrontendBase to 10.0.22 to pick up the new
property and DB migration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Migrate theme.scss and custom component mixins to pure Material 3:
drop mat.m2-* typography, palettes and color helpers; use
mat.define-theme with brand-family/plain-family; replace the global
button border-radius block with mat.button/icon-button/fab-overrides;
rewrite text/table/chart/tag/ngx-editor/ngx-gallery/ngx-toastr mixins
to read from CSS custom properties instead of M2 theme maps.

Prerequisite for introducing per-theme density/shape overrides in
the upcoming Workspace theme variant.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Introduce scss/themes/_eform.scss exporting an $eform-tokens map
(palette, font families, density, button/icon-button/fab/dialog
shapes) and scss/themes/_theme-mixin.scss with apply-theme($tokens,
$mode), which builds the M3 theme and emits component overrides from
the map.

theme.scss becomes an orchestrator calling apply-theme for
body.theme-light and body.theme-dark. The previous html-level button
overrides and .cdk-overlay-container dialog overrides are removed now
that the mixin owns them — single source of truth.

Preparation for dropping in a second theme (Workspace) that reuses the
same mixin with a different token map.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Introduce scss/themes/_workspace.scss exporting $workspace-tokens
(mat.$azure-palette, Google Sans / Roboto family stacks, density -1,
dialog 28px, fab 16px, card 16px, chip 8px, button 20px pill).

Extend $eform-tokens with card-shape and chip-shape, holding the
Material 3 defaults (12px and 8px) so eform renders identically. The
apply-theme mixin now emits mat.card-overrides and mat.chips-overrides
from these tokens.

theme.scss keeps body.theme-light and body.theme-dark as the default
eform selectors so today's runtime still works, and adds
body.theme-workspace.theme-light / .theme-dark selectors that win on
specificity when runtime toggles the class in step 6.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…le sidebar

Adds the Google Workspace visual variant alongside the eForm classic tokens
and completes the pure-M3 theme mixin. The mixin now emits both Material
component overrides (button / form-field / table / list / card / chip /
dialog) and the legacy CSS custom properties the app reads (--primary,
--bg, --card, --font-family, etc.) so non-Material elements and plugins
pick up the theme without any component changes.

The navigation sidebar is restyled to match Google Calendar's density:
36px row height, 14px Google Sans 500, 16px gaps between both leaf and
expandable items, aligned indentation at the same left edge, neutral
#e8eaed selected pill with dark text, and hover on --hover-surface.
Expandable headers no longer show the old navy hover.

Also wires a content-card wrapper inside the full layout so the routed
content sits on a white rounded card floating on the #f0f4f9 page surface,
and preconnects Google Sans in index.html.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Table: neutral grey row hover (#f1f3f4), soft-blue selected row,
  sticky Actions column inherits row background instead of grey
- mat-menu: 12px radius, soft shadow, 36px rows, edge-to-edge grey hover
- ng-select dropdown: 12px radius, soft shadow, grey hover, soft-blue
  selected, text stays readable on hover
- Form fields: filled --input-fill bg, 40px height, blue focus underline,
  collapse empty subscript wrapper
- ngx-editor: --input-fill bg to match inputs (overrode stale rule in
  styles.scss that forced --bg)
- Buttons: 36px height across btn-primary/secondary/cancel/warning/delete
- Subheader card: --card bg with 12px radius
- Sidebar nav items bumped to Drive proportions (40px leaf, 20px icons)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Three-phase plan to extract every hardcoded visual value across the host
app and all plugin source repos into a single token vocabulary, then
mechanically replace hardcodes with var(--...) references, gated by a
Playwright screenshot-regression diff against current stable.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bite-sized task plan covering: preserve current state, build screenshot
baseline harness, capture stable baseline, vocabulary audit + review
gate, populate eform/workspace token maps, mechanical replace via
parallel subagents (host + 18 plugins), gap resolution, screenshot diff
+ fix loop, PR coordination, and rebase of picker UI onto consolidated
stable.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…dation

Snapshot before starting M3 token consolidation on a fresh branch.
Includes:
- Backend ThemeVariant plumbing (AppearanceSettings POCO, Program.cs
  seeding, CmsService + SettingsService read/write, AdminSettingsModel
  + CmsPublicConfigModel fields).
- Frontend state plumbing (cms actions/effects/reducer/selectors with
  themeVariant, models, app.component.ts theme-class subscription).
- Admin settings theme picker UI (cards at the bottom of the page).
- In-progress eform parity SCSS (token additions, dropdown/nav/button
  pixel-match work) — superseded by the consolidation branch but kept
  cherry-pickable.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant